# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1069.45.2 -> 1.1069.45.3 # fs/hugetlbfs/inode.c 1.5 -> 1.6 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/09/30 kenneth.w.chen@intel.com 1.1069.45.3 # HUGETLBFS: fix mount error paths # # Here is a patch that fixes a rather nasty bug in hugetlbfs. If root # tries to mount a hugetlbfs with invalid mount option, # hugetlbfs_fill_super incorrectly returns error code instead of NULL on # couple error conditions, causing generic vfs layer to segfault and took # some semaphore with it, the end result is kernel hang on any subsequent # file system mount/unmount. There are some other cases that has memory # leak upon error conditions. # -------------------------------------------- # diff -Nru a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c --- a/fs/hugetlbfs/inode.c Thu Oct 9 15:20:22 2003 +++ b/fs/hugetlbfs/inode.c Thu Oct 9 15:20:22 2003 @@ -601,23 +601,21 @@ { struct inode * inode; struct dentry * root; - int ret; struct hugetlbfs_config config; struct hugetlbfs_sb_info *sbinfo; - sbinfo = kmalloc(sizeof(struct hugetlbfs_sb_info), GFP_KERNEL); - if (!sbinfo) - return -ENOMEM; - sb->u.generic_sbp = sbinfo; - config.nr_blocks = -1; /* No limit on size by default. */ config.nr_inodes = -1; /* No limit on number of inodes by default. */ config.uid = current->fsuid; config.gid = current->fsgid; config.mode = 0755; - ret = hugetlbfs_parse_options(data, &config); - if (ret) - return ret; + if (hugetlbfs_parse_options(data, &config)) + return NULL; + + sbinfo = kmalloc(sizeof(struct hugetlbfs_sb_info), GFP_KERNEL); + if (!sbinfo) + return NULL; + sb->u.generic_sbp = sbinfo; spin_lock_init(&sbinfo->stat_lock); sbinfo->max_blocks = config.nr_blocks; @@ -631,15 +629,18 @@ inode = hugetlbfs_get_inode(sb, config.uid, config.gid, S_IFDIR | config.mode, 0); if (!inode) - return NULL; + goto out_free; root = d_alloc_root(inode); if (!root) { iput(inode); - return NULL; + goto out_free; } sb->s_root = root; return sb; +out_free: + kfree(sbinfo); + return NULL; } static DECLARE_FSTYPE(hugetlbfs_fs_type, "hugetlbfs", hugetlbfs_fill_super, FS_LITTER);